package alexattar.gdxtest.services;

import alexattar.gdxtest.GdxTestGame;
import alexattar.gdxtest.services.SoundManager.TyrianSound;
import alexattar.gdxtest.utils.LRUCache;
import alexattar.gdxtest.utils.LRUCache.CacheEntryRemovedListener;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Disposable;

public class SoundManager implements CacheEntryRemovedListener<TyrianSound, Sound>, Disposable {

	public enum TyrianSound {
		CLICK("sound/click.wav");
		private final String fileName;
		
		private TyrianSound(String filename) {
			this.fileName = filename;
		}
		
		public String getFileName() {
			return fileName;
		}
	}
	
	private float volume = 1f;
	private boolean enabled = true;
	private final LRUCache<TyrianSound, Sound> soundCache;
	
	public SoundManager() {
		soundCache = new LRUCache<SoundManager.TyrianSound, Sound>(10);
		soundCache.setEntryRemovedListener(this);
	}
	
	public void play(TyrianSound sound) {
		if (!enabled) return;
		
		Sound soundToPlay = soundCache.get(sound);
		if (soundToPlay == null) {
			FileHandle soundFile = Gdx.files.internal(sound.getFileName());
			soundToPlay = Gdx.audio.newSound(soundFile);
			soundCache.add(sound, soundToPlay);
		}
		
		Gdx.app.log(GdxTestGame.LOG, "Playing sound: " + sound.name());
		soundToPlay.play(volume);
	}
	
	public void setVolume(float volume) {
		Gdx.app.log(GdxTestGame.LOG, "Adjusting sound volume to: " + volume);
		
		if(volume < 0 || volume > 1) {
			throw new IllegalArgumentException("The volume must be inside the range: [0,1]");
		}
		this.volume = volume;
	}
	
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}
	
	@Override
	public void dispose() {
		Gdx.app.log(GdxTestGame.LOG, "Disposing sound manage" );
		for(Sound sound : soundCache.retrieveAll()) {
			sound.stop();
			sound.dispose();
		}
	}

	@Override
	public void notifyEntryRemoved(TyrianSound key, Sound value) {
		Gdx.app.log(GdxTestGame.LOG, "Disposing sound: " + key.name());
		value.dispose();
	}

}
